#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define BTCM_READ_OFFSET   (0x8000)
#define BTCM_WRITE_OFFSET   (0x0)
#define BTCM_UIO_NAME   ("/dev/uio1")
#define BTCM_UIO_SIZE (0x10000)
#define BTCM_SYS_UIO_NAME   ("/sys/class/uio/uio1/")

/*获取预留内存块的起始物理地址*/
static uint64_t mem_physical_addr_get(void)
{
    int32_t uio_mem_addr_fd = -1;
    int8_t uio_addr_filename[128] = {0};
    uint64_t phy_addr = 0;
    uint8_t buf[32] = {0};
    int32_t ret = 0;

    sprintf(uio_addr_filename, "%s/maps/map0/addr", BTCM_SYS_UIO_NAME);

    printf("uio mem addr filename:%s\n", uio_addr_filename);
    uio_mem_addr_fd = open(uio_addr_filename, O_RDONLY);
    if (-1 == uio_mem_addr_fd)
    {
        printf("get UIO memory size failed\n");
        return -1;
    }

    ret = read(uio_mem_addr_fd, (void *)&buf, sizeof(buf));
    if (-1 == ret)
    {
        printf("read UIO mem size failed\n");
        close(uio_mem_addr_fd);
        return -1;
    }

    sscanf(buf, "0x%lx", &phy_addr);
    close(uio_mem_addr_fd);

    printf("reserved memory physical addr:0x%lx\n", phy_addr);

    return phy_addr;
}

int main(int argc, char *argv[])
{
    int fd = -1;
    void *map_addr = NULL;
    size_t size = BTCM_UIO_SIZE;
    volatile uint32_t *mapped = NULL;
    volatile uint32_t read_data = 0;
    volatile uint32_t write_data = 0x1000;
    uint64_t phy_addr = 0;

    fd = open(BTCM_UIO_NAME, O_RDWR);
    if (fd < 0) 
    {
        perror("Failed to open devfile");
        return 1;
    }

    map_addr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map_addr == MAP_FAILED)
    {
        perror("Failed to mmap");
        return 1;
    }

    phy_addr = mem_physical_addr_get();

    mapped = map_addr;
    printf("mmaped reserved memory addr:%p, physical addr:0x%lx\n", map_addr, phy_addr);

    while(1)
    {
        read_data = *((uint32_t *)((uint8_t *)mapped + BTCM_READ_OFFSET));
        printf("read btcm addr 0x%lx, data:0x%x\n", phy_addr + BTCM_READ_OFFSET, read_data);

        *((uint32_t *)((uint8_t *)mapped + BTCM_WRITE_OFFSET)) = write_data;
        printf("write btcm addr 0x%lx, data:0x%x\n", phy_addr + BTCM_WRITE_OFFSET, write_data);
        write_data += 8;
        printf("\n");

        sleep(1);
    }    


    munmap(map_addr, size);

    close(fd);

    return 0;
}


